# 导入 pandas 库，用于处理 Excel 数据
import pandas as pd
# 导入 tkinter 库，用于创建图形用户界面
import tkinter as tk
# 从 tkinter 中导入 filedialog 模块，用于打开文件选择对话框
from tkinter import filedialog

# 定义处理 Excel 文件的函数
def process_excel():
    # 更新状态标签的文本，提示用户正在选择文件
    status_label.config(text="正在选择文件...")
    # 立即更新界面，显示最新的状态信息
    root.update_idletasks()
    # 打开文件选择对话框，只允许选择 Excel 文件（.xlsx 或 .xls 格式）
    file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx;*.xls")])
    # 如果用户没有选择文件
    if not file_path:
        # 更新状态标签的文本，提示用户未选择文件
        status_label.config(text="未选择文件，请重新操作。")
        # 退出函数
        return
    try:
        # 更新状态标签的文本，提示用户正在读取 Excel 文件
        status_label.config(text="正在读取 Excel 文件...")
        # 立即更新界面，显示最新的状态信息
        root.update_idletasks()
        # 读取指定路径下的 Excel 文件，选择名为 'Sheet1' 的工作表
        df = pd.read_excel(file_path, sheet_name='Sheet1')

        # 提取 DataFrame 的前 5 列的列名，作为固定列的列名
        id_cols = df.columns[:5].tolist()

        # 提取第 1 行（索引为 0）中从第 6 列（索引为 5）到第 17 列（索引为 16）的值，作为动态列名
        dynamic_col_names = df.iloc[0, 5:17].tolist()

        # 初始化一个空列表，用于存储处理后的数据
        result_data = []

        # 遍历 DataFrame 的每一行，从第 1 行（索引为 0）开始
        for _, row in df[0:].iterrows():
            # 遍历从第 6 列（索引为 5）到第 17 列（索引为 16）
            for col_idx in range(5, 17):
                # 获取当前行中固定列的值，并转换为列表
                new_row = row[id_cols].tolist()
                # 将当前列的列名添加到新行列表中，可能作为 '月份' 列的值
                new_row.append(df.columns[col_idx])
                # 将当前行中该列的值添加到新行列表中，作为 '目标' 列的值
                new_row.append(row[df.columns[col_idx]])
                # 将新行添加到结果数据列表中
                result_data.append(new_row)

        # 使用处理后的数据创建一个新的 DataFrame，并指定列名
        result_df = pd.DataFrame(result_data, columns=id_cols + ['月份', '目标'])

        # 按照 F，A，B，C 列升序排序
        sort_columns = [result_df.columns[i] for i in [5, 0, 1, 2]]
        result_df = result_df.sort_values(by=sort_columns, ascending=True)

        # 处理生成 Sheet3 的数据，从 result_df（即 小组层级 对应的数据）中操作
        # 按照 A 、 B 、 D 、 E 、F 列进行分组
        group_cols = [result_df.columns[i] for i in [0, 1, 3, 4, 5]]
        # 对 G 列求和
        sum_cols = [result_df.columns[6]]
        df_grouped_sum = result_df.groupby(group_cols)[sum_cols].sum().reset_index()
        # 对 C 列进行拼接
        df_grouped_concat = result_df.groupby(group_cols)[result_df.columns[2]].agg(lambda x: ','.join(map(str, x))).reset_index()
        # 合并求和和拼接的结果
        df_sheet3 = pd.merge(df_grouped_sum, df_grouped_concat, on=group_cols)

        # 按照 F，A，B，C 列升序排序
        sort_columns_sheet3 = [df_sheet3.columns[i] for i in [4, 0, 1]]
        df_sheet3 = df_sheet3.sort_values(by=sort_columns_sheet3, ascending=True)

        # 更新状态标签的文本，提示用户正在写入新的 Excel 工作表
        status_label.config(text="正在写入新的 Excel 工作表...")
        # 立即更新界面，显示最新的状态信息
        root.update_idletasks()
        # 使用 openpyxl 引擎以追加模式打开 Excel 文件，如果 'Sheet2' 工作表已存在则替换
        with pd.ExcelWriter(file_path, engine='openpyxl', mode='a', if_sheet_exists='replace') as writer:
            # 将处理后的 DataFrame 写入 'Sheet2' 工作表，不保存索引，每列宽度设为100
            result_df.to_excel(writer, sheet_name='小组层级', index=False)
            # 获取 'Sheet2' 工作表对象
            worksheet = writer.sheets['小组层级']
            # 遍历每一列，设置列宽为 20
            for column_cells in worksheet.columns:
                length = 20
                worksheet.column_dimensions[column_cells[0].column_letter].width = length

            # 生成 orgmain 工作表的数据
            # grouped_data = []
            # unique_values = df['BG'].unique()
            # for value in unique_values:
            #     for num in range(1, 13):
            #         grouped_data.append([value, num])
            # grouped_df = pd.DataFrame(grouped_data, columns=['BG', '月份'])

            # # 将分组数据写入 orgmain 工作表
            # grouped_df.to_excel(writer, sheet_name='orgmain', index=False)

            # 将处理后生成 Sheet3 的数据写入 'Sheet3' 工作表
            df_sheet3.to_excel(writer, sheet_name='Sheet3', index=False)

        # 更新状态标签的文本，提示用户处理完成
        status_label.config(text="处理完成！")
    # 捕获处理过程中可能出现的异常
    except Exception as e:
        # 更新状态标签的文本，显示出错信息
        status_label.config(text=f"处理出错：{str(e)}")


# 创建 tkinter 主窗口
root = tk.Tk()
# 设置主窗口的大小为 800x400 像素
root.geometry("800x400")
# 设置主窗口的标题
root.title("业绩目标标准Excel 数据处理工具")

# 创建一个按钮，点击按钮时调用 process_excel 函数
process_button = tk.Button(root, text="选择 业绩目标标准Excel 文件并处理", command=process_excel)
# 将按钮放置在窗口中，垂直方向上留出 20 像素的间距
process_button.pack(pady=20)

# 创建一个标签，显示提示信息
status_label = tk.Label(root, text="请点击按钮选择文件\n\n注意：检查BG、BU、小组、客户、产品线是否系统里都有，没有请修改后再生成")
# 将标签放置在窗口中，垂直方向上留出 10 像素的间距
status_label.pack(pady=10)

# 启动 tkinter 的主事件循环，使窗口保持显示状态
root.mainloop()